<?php
namespace Yls\Core;
use Yls;

/**
 *  // 传递过来的参数数据: 
 *  [
 *      'id' => 1,
        'nick' => ['LIKE' => 'hello'],
        'age' => ['>=' => 10, '<' => 30]
    ]
    
    $Condition = new Yls\Core\Condition((object)[
        'select' => 'id, fRoute, fName',
        'group' => '',
        'having' => '',
        'order' => '',
        'offset' => 1,
        'size' => 5,
    ], [
        'id', 'active' => '~~buz.~User.active', 'nick' => '~User.nick'
    ]);
    
    // 获取数据
    Yls::Db()->From('User')->FetchAll($Condition);
 */
class Condition {
    
    private $_map = [];
    private $_condition = '';
    private $_joints = [];
    
    /**
     * 初始化
     * @param stdClass $condition 条件
     * @param array $map 参数-字段映射关系
     */
    public function __construct($condition, array $map = []) {
        $this->_condition = (object)$condition;
        $this->MakeWhere($map);
        $this->_map = (array)$map;
    }
    
    public function __set($item, $value) {}
    
    /**
     * 获取条件信息
     * @param string where|group|having|order|offset|size|lock
     * @return string|false
     */
    public function __get($item) {
        switch($item) {
            case 'where':
                return implode(' AND ', $this->_joints);
            case 'group':
            case 'having':
            case 'order':
            case 'offset':
            case 'size':
            case 'lock':
            default:
                return isset($this->_condition->{$item}) ? $this->_condition->{$item} : false;
        }
    }
    
    /**
     * 添加where条件
     * @param string $rule 规则
     * @param string $field 字段
     * @param mixed $value
     */
    public function WhereAdd($rule, $field, $value) {
        $this->_joints[] = $this->Dispatch($rule, $field, $value);
    }
    
    // @todo
    public function WhereOr() {
        
    }
    
    /**
     * 根据当前参数及绑定信息构造完整WHERE条件
     * @param array $map
     */
    private function MakeWhere(array $map) {
        foreach($map as $param=>$field) {
            $joint = $this->Joint(is_numeric($param) ? $field : $param, $field);
            if($joint) $this->_joints = array_merge($this->_joints, $joint);
        }
    }
    
    private function Joint($param, $field) {
        if(false === ($result = Yls::Instance()->Param($param))) return false;
        $result = Yls::Instance()->Param($param);
        $joints = [];
        if(is_object($result)) {
            foreach($result as $rule=>$value) {
                $joint = $this->Dispatch($rule, $field, $value);
                if(strlen($joint)) $joints[] = $joint;
            }
        } else {
            $joint = $this->Dispatch('=', $field, $result);
            if(strlen($joint)) $joints[] = $joint;
        }
        return $joints;
    }
    
    /**
     * 根据当前规则进行分发处理
     * @param string $rule 规则
     * @param string $field 字段
     * @param mixed $value
     */
    private function Dispatch($rule, $field, $value) {
        switch(strtoupper($rule)) {
            case '=':
            case '<':
            case '<=':
            case '>':
            case '>=':
            case '<>':
            case '!=':
                return (is_null($value) || (is_string($value) && !strlen($value))) ? '' : ($field.' '.$rule.' "'.$value.'"');
            case 'LIKE':
    		    return strlen($value) ? $field.' LIKE "%'.$value.'%"' : '';
            case 'BETWEEN':
                return (!empty($value) && is_array($value)) ?  $field.' BETWEEN "'.$value[0].'" AND "'.$value[1].'"' : '';
    		case 'IN':
    		    return $field.' IN ('.implode('", "', $value).')';
		    case 'NOT IN':
		        return $field.' NOT IN ('.implode('", "', $value).')';
		    case 'NULL':
		        return $field.' IS '.($value ? 'NULL' : 'NOT NULL');
    		default:
    		    return '';
        }
    }
}